package test.chat.server;

import java.util.HashMap;
import java.util.Map;

import test.chat.common.command.Command;
import test.chat.common.command.LoginRequestCommand;
import test.chat.common.command.LoginResponseCommand;
import test.chat.common.command.MessageCommand;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.n1global.asts.EndpointContext;
import com.n1global.asts.message.websocket.WebSocketMessage;
import com.n1global.asts.protocol.websocket.WebSocketEventHandler;

public class ChatWebSocketHandler extends WebSocketEventHandler {
    private static final Map<String, EndpointContext<WebSocketMessage>> connections = new HashMap<>();

    private static ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public void onDisconnect(Exception e) {
        if (getEndpointContext().getPayload() != null) {
            String login = (String) getEndpointContext().getPayload();

            connections.remove(login);
        }
    }

    @Override
    public void onDataMessage(WebSocketMessage webSocketMsg) {
        Command command;

        String msg = webSocketMsg.convertBytes2String();

        try {
            command = objectMapper.readValue(msg, Command.class);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        if (command instanceof LoginRequestCommand) {
            if (getEndpointContext().getPayload() == null) {
                LoginRequestCommand request = (LoginRequestCommand) command;

                LoginResponseCommand response = new LoginResponseCommand();

                if(!connections.containsKey(request.getUserName())) {
                    getEndpointContext().setPayload(request.getUserName());

                    connections.put(request.getUserName(), getEndpointContext());
                } else {
                    response.setErrorMessage("Данное имя пользователя уже используется!");
                }

                send(response, getEndpointContext());
            }
        }

        if (command instanceof MessageCommand) {
            MessageCommand c = (MessageCommand) command;

            if (getEndpointContext().getPayload() != null) {
                c.setFromUser((String) getEndpointContext().getPayload());//retrieve real user name

                for(EndpointContext<WebSocketMessage> _ctx : connections.values()) {
                    send(c, _ctx);
                }
            }
        }
    }

    protected void send(Command command, EndpointContext<WebSocketMessage> ctx) {
        try {
            String json = objectMapper.writeValueAsString(command);

            ctx.getSender().send(new WebSocketMessage(json));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
